#include "useful_functions.h"
#include "global_variables.h"

void to_html(const record_set &rs, string &output) {
  output.clear();

  const unsigned int rows = rs.get_row_count();
  const unsigned int columns = rs.get_column_count();
  if (columns == 0)
    return;

  const char *data = 0;

  output.reserve(8 * rows * columns);
  output = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">";
  output += "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">";
  output += "<head><meta content=\"text/html; charset=utf-8\" http-equiv=\"content-type\" />";
  output += "<title></title></head>";
  output += "<body><table border='1' width='100%'>";

  output += "<tr>";
  for (unsigned int j = 0; j < columns; ++j) {
    output += "<th>";

    data = rs.get_column_name(j);
    if (data != 0)
      output += data;

    output += "</th>";
  } // for j
  output += "</tr>";

  for (unsigned int i = 0; i < rows; ++i) {
    output += "<tr>";

    for (unsigned int j = 0; j < columns; ++j) {
      output += "<td>";

      data = rs(i, j);
      if (data != 0)
        output += data;
      else
        output += "&nbsp;"; // an empty cell

      output += "</td>";
    } // for j

    output += "</tr>";
  } // for i

  output += "</table></body></html>";
} // to_html

void to_string(const record_set &rs, string &output, char column_separator, char row_separator) {
  output.clear();

  const unsigned int rows = rs.get_row_count();
  const unsigned int columns = rs.get_column_count() - 1;
  if ((columns + 1) == 0)
    return;

  output.reserve(8 * rows * columns);

  const char *data = 0;
  for (unsigned int i = 0; i < rows; ++i) {
    for (unsigned int j = 0; j < columns; ++j) {
      data = rs(i, j);
      if (data != 0)
        output += data;

      output += column_separator;
    } // for j

    data = rs(i, columns);
    if (data != 0)
      output += rs(i, columns);

    output += row_separator;
  } // for i
} // to_string

void to_string(const list<string> &l, string &output, char marker /*= '\''*/, char separator /*= ','*/) {
  output.clear();
  output.reserve(8 * l.size());

  for (auto it = l.cbegin(); it != l.cend(); ++it) {
    output += separator;
    output += marker;
    output += *it;
    output += marker;
  } // for

  output.erase(0, 1);
} // to_string

void binary_read(const string &file_name, smart_array<char> &output) {
  output.clear();

  ifstream in_file(file_name.c_str(), ios::binary);
  if (in_file.good() == true) {
    in_file.seekg(0, ios::end); // end of the file
    const size_t file_size = in_file.tellg();
    in_file.seekg(0, ios::beg); // beginning of the file

    output.set_size(file_size + 1);
    in_file.read(output.get(), file_size);
    output[file_size] = '\0';
  }

  in_file.close();
}

void binary_read(const string &file_name, string &output) {
  output.clear();

  FILE *f = fopen(file_name.c_str(), "rb");
  if (f == 0)
    return;

  if (fseek(f, 0, SEEK_END) == 0) { // go to the end of the file
    const long len = ftell(f);
    if (fseek(f, 0, SEEK_SET) == 0) { // go to the begining of the file
      output.reserve(len);

      size_t n = 0;

      const int buffer_size = 32 * 1024;
      char buffer[buffer_size + 1] = { "\0" };
      do {
        n = fread(buffer, sizeof(char), buffer_size, f);
        if (n != 0)
          output.append(buffer, n);

      } while (n == buffer_size);
    } // if
  } // if

  fclose(f);
}

void binary_write(const string &file_name, const string &input, bool append) {
  ios_base::openmode mode = ios::binary;
  if (append == false)
    mode |= ifstream::out;
  else
    mode |= ifstream::app; // append

  ofstream o1(file_name.c_str(), mode);
  if (o1.good() == true)
    o1 << input;

  o1.close();
}
